import {
  Controller,
  Get, Post, Redirect, HttpCode, Header,
  Req, Request, Query, Headers, Session, Ip, Param, Body, Res, Response, Next, Inject,
} from '@nestjs/common'
import { Request as ExpressRequest, Response as ExpressResponse } from 'express'
// 自定义参数装饰器
import { User } from './user.decorator'

// 服务 （ 提供者 ）
import {
  LoggerClassService,
  LoggerService,
  UseValueService,
  UseFactory
} from './logger.service'

@Controller()
export class AppController {
  constructor(
    private loggerClassService: LoggerClassService,
    private loggerService: LoggerService,
    @Inject('StringToken') private useValueService: UseValueService,
    @Inject('FactoryToken') private useFactory: UseFactory,
    @Inject('use_value') private useValue: string
  ) { }

  @Get('logger')
  loggerHandle() {
    this.loggerClassService.log()
    this.loggerService.log()
    this.useValueService.log()
    this.useFactory.log()
    console.log(this.useValue)

    // console.log(
    //   this.loggerClassService, 
    //   this.loggerService, 
    //   this.useValueService, 
    //   this.useFactory,
    //   this.useValue
    // )

    return 'hello world'
  }

  @Get('info')
  getHello(@Req() req: ExpressRequest, age: any, @Request() request: ExpressRequest) {
    console.log(age, 'age')
    console.log(req.url, request.url) // /info /info
    console.log(req.path, request.path)
    console.log(req.method, request.method)
    return 'hello'
  }

  @Get('query')
  handleQuery(@Query() query: any, @Query('id') id: string) {
    console.log('query ', query)
    console.log('id ', typeof id, id)
    return `query`
  }

  @Get('headers')
  handleHandlers(@Headers() handlers: any, @Headers('accept') accept: string) {
    console.log('handlers ', handlers)
    console.log('accept ', accept)
    return 'headers'
  }

  @Get('session')
  handleSession(@Session() session) {
    const { pageView } = session
    console.log('session ', session)
    console.log('pageView ', pageView)
    if (session.pageView) {
      session.pageView++
    } else {
      session.pageView = 1
    }
    return `pageView: ${session.pageView}`
  }

  @Get('ip')
  getUserIP(@Ip() ip: string) {
    return `ip: ${ip}`
  }

  @Get(':username/info/:age')
  getUserNameInfo(@Param() param, @Param('username') username: string, @Param('age') age: string) {
    console.log(param, username, age)
    return `username: ${username}, age: ${age}`
  }

  // * 代表任意字符
  @Get('star/ab*de')
  handleWildcard() {
    return `handleWildcard`
  }

  @Post('created')
  handleCreated(@Body() createUserDto, @Body('username') username: string) {
    console.log('createUserDto', createUserDto)
    console.log('username', username)
    return `handleCreated`
  }

  @Post('response')
  handleResponse(@Response() response: ExpressResponse) {
    // 使用 @Res() 或 @Response() 装饰器时需要手动处理响应 
    response.send('手动响应 handleRes')
  }

  @Post('res')
  handleRes(@Res({ passthrough: true }) res: ExpressResponse) {
    res.setHeader('key', 'value')
    // 使用 @Res() 或 @Response() 装饰器时需要手动处理响应 
    // 如何使用了 { passthrough: true } 则会将响应控制权重新交给 nestjs 来处理
    return '通过配置 {passthrough: true} 将响应交给 nestjs 来处理6'
  }

  @Get('nest')
  handleNext(@Next() next) {
    // 当使用 @Next() 装饰器时 响应控制权会用用户来处理
    next()
  }

  @Get('next')
  handleNext2() {
    return 'handle Next 装饰器'
  }

  // 通过参数装饰器来指定重定向路径和响应状态码
  @Get('redirect')
  @Redirect('/ip', 302)
  handleRedirect() {
  }

  // 通过返回 符合 HttpRedirectResponse 接口的对象来动态指定重定向路径和响应状态码
  // 返回的对象会覆盖 @Redirect() 装饰器指定的重定向路径和响应状态码
  @Redirect('/ip')
  @Get('redirect2')
  handleRedirect2(@Query('version') version) {
    // http://localhost:3000/redirect2?version=v5
    // https://docs.nestjs.com/v5/
    return {
      url: `https://docs.nestjs.com/${version}?version=${version}`,
      statusCode: 303,
    }
  }

  // 设置响应状态码
  @Post('created2')
  @HttpCode(202)
  handleCreated2() {
    return 'handleCreated2'
  }

  // 设置2个自定义响应头
  @Get('header')
  @Header('key1', 'value1')
  @Header('key2', 'value2')
  handleHeader() {
    return 'handleHeader'
  }

  // 使用自定义参数装饰器 @User()
  @Get('user')
  handleUser(@Req() req, @User() userInfo: any, @User('name') name: string) {
    console.log(userInfo, 'userInfo')
    console.log(name, 'name')
    return req.user
  }
}
